/*
*	title: root.c
*
*	Code for the root level of the distributed system.
*	This peace of code determines the sorting of a integer vector with 1000 elements, 
*	passing it through the socket back to it´s original server.
*	The 1000 elements come from the secondL level connected through socket.
*
*	Date: 22/09/2013
*	Autors: Danilo Barbosa Porto , Henrique Alberto Rusa
*/

#include<sys/timeb.h>
#include <time.h>
#include<errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "tcptoken.h"


#define RECEIVED_VECTOR 500 		// server receive 500 integers from each client
#define SENDING_VECTOR 1000		// server sends 1000 integers over socket


// function to compare two integers used on the qsort function call 
int comp (const void *a, const void *b);

// function to calculate the time interval of execution
float time_dif(struct timeb end, struct timeb start);

/*
*	Main function.
*	Parameters:	root <PortNumberToServer>  
*/
int main (int argc, char *argv[]) {

	// variables to calculate the time interval
	struct timeb startConnecr,startConnecl;
	struct timeb endConnecr,endConnecl;
	struct timeb startSort,endSort;
	
	// arguments verification
	if ( argc < 1) {
		fprintf(stderr,"ERROR [%s] usage root <PortNumberToServer>: %s \n", argv[0], strerror(errno));
		exit(0);
	}
	
	// getting port number from first argument
	int portno = atoi(argv[1]);
	
	// client of connection to receive and send the data through socket
	servtoken servr,servl;
	
	// Allocating the servers given the port to connect
	newServer( &servl, portno );
	newServer( &servr, portno + 1 );
	
	/*  
	*	outputBuffer - buffer used to send 1000 integers through the connection from each client
	*	middleOutBuffer - buffer used to point to the middle of the outoutBuffer
	*	storageBuffer - buffer used to store the original vector received
	*/
	int *outputBuffer;
	int *middleOutBuffer;
	int *storageBuffer;

	outputBuffer = (int *)malloc( SENDING_VECTOR * sizeof(int));
	middleOutBuffer = &outputBuffer[RECEIVED_VECTOR];
	storageBuffer = (int *)malloc(SENDING_VECTOR * sizeof(int));
	
	// error treatment over memory allocation to buffers
	if ( outputBuffer == NULL ) {
		fprintf(stderr,"ERROR [%s] while allocating memory to the buffers used; %s \n",argv[0], strerror(errno));
		exit(0);
	} 
	
	/*
	*	Starting servers.
	*	this function waits for connection.
	*	this call block the program.
	*/
	serverStart( &servl );
	ftime(&startConnecl);
	serverStart( &servr );
	ftime(&startConnecr);
	
	/*
	* 	Our program receives data through both servers.
	*	Data received will be concatenated using two pointers 
	*	to the same vector.
	*	So we utilize a pointer on the middle of the bigger one
	*	to pass as a buffer to the second half of data.
	*/
	int r,l; r = l = 0;
	l = serverRead( &servl, (void *)outputBuffer, sizeof(int) * RECEIVED_VECTOR);
	r = serverRead( &servr, (void *)middleOutBuffer, sizeof(int) * RECEIVED_VECTOR);
	if(( r < 0)||( l < 0)) {
		fprintf(stderr,"ERROR [%s] server reading from socket: %s \n",argv[0], strerror(errno));
		exit(0);
	}

	// store the received vector
	memcpy( storageBuffer,outputBuffer,RECEIVED_VECTOR * sizeof(int) );
	
	// call to sort for the concatenated vector
	ftime(&startSort);
	qsort( outputBuffer, SENDING_VECTOR, sizeof(int), &comp);
	ftime(&endSort);
	
	/*
	*	With the sorted vector at our buffer we initiate the transport
	*	to the seconds.
	*	We will use the servers allocated to write to the seconds.
	*/
	r = l = 0;
	l = serverWrite( &servl, (void *)outputBuffer, sizeof(int) * SENDING_VECTOR);
	r = serverWrite( &servr, (void *)outputBuffer, sizeof(int) * SENDING_VECTOR);
	if(( r < 0)||( l < 0)) {
		fprintf(stderr,"ERROR [%s] server reading from socket: %s \n", argv[0], strerror(errno));
		exit(0);
	}

	// Closing the instances of the servers used
	closeServer( &servl );
	ftime(&endConnecl);
	closeServer( &servr );
	ftime(&endConnecr);
	
	return 0;
}

// function to compare two integers used on the qsort function call 
int comp (const void *a, const void *b) {
	return ( *(int *)a - *(int *)b );
}

// function to calculate the time interval of execution
float time_dif(struct timeb end, struct timeb start) {
	float dif;
	return dif = (float)((end.time - start.time) + 0.001*(end.millitm - start.millitm));
}




















